package ru.amse.stroganova.ui.visual;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke;

import ru.amse.stroganova.presentation.EdgePresentation;
import ru.amse.stroganova.presentation.VertexPresentation;

/**
 * Represents class for imaginary edge which is not contained in any presentation.
 * 
 * @author Dasha Stroganova
 *
 */
public class ImaginaryEdge {

	private final EdgePresentation imaginaryEdge;
	
	private final VertexPresentation movingVertex;
	
	private final VertexPresentation fixedVertex;
	
	private final BasicStroke DASHED_STROKE = new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, new float[]{4.0f}, 0.0f);
	
	/**
	 * Creates new imaginare edge.
	 * 
	 * @param fixedCenter
	 * @param movingCenter
	 * @param isSourceFixed
	 * @param isDirected
	 * @param isWeighted
	 * @param weight
	 */
	public ImaginaryEdge(Point fixedCenter, Point movingCenter, boolean isSourceFixed, boolean isDirected, boolean isWeighted, int weight) {
		fixedVertex = new VertexPresentation(fixedCenter);
		movingVertex = new VertexPresentation(movingCenter);
		if (isSourceFixed) {
			imaginaryEdge = new EdgePresentation(fixedVertex, movingVertex, isDirected, isWeighted);
		} else {
			imaginaryEdge = new EdgePresentation(movingVertex, fixedVertex, isDirected, isWeighted);
		}
		imaginaryEdge.setWeight(weight);
	}
	
	/**
	 * Moves unfixed edge end.
	 * 
	 * @param point
	 */
	public void moveEnd(Point point) {
		movingVertex.setCenter(calculateImaginaryVertexCenter(point));
	}
	
	private Point calculateImaginaryVertexCenter(Point point) {
		double alpha = Math.atan((double) (fixedVertex.getCenter().y - point.y) / (fixedVertex.getCenter().x - point.x));
		if ((fixedVertex.getCenter().x - point.x) < 0) {
			alpha += Math.PI;
		}
		double centerX = point.x - VertexPresentation.RADIX * Math.cos(alpha);
		double centerY = point.y -  VertexPresentation.RADIX * Math.sin(alpha);
		return new Point((int) Math.round(centerX), (int) Math.round(centerY));
	}
	
	/**
	 * Paints imaginary edge.
	 * 
	 * @param gr
	 * @param backgroundColor
	 */
	public void paint(Graphics gr, Color backgroundColor) {
		Graphics2D gr2D = (Graphics2D) gr;
		Stroke prevStroke = gr2D.getStroke();
		gr2D.setStroke(DASHED_STROKE);
		imaginaryEdge.paint(gr2D, backgroundColor);
		gr2D.setStroke(prevStroke);
	}
}
